# -*- coding: utf-8 -*-
#
# fusion.tracker.Coast
#
# Copyright 2007 Helsinki Institute for Information Technology
# and the authors.
#
# Authors: Toni Ruottu <toni.ruottu@iki.fi>
#          Harri Hämäläinen <harri.hamalainen@helsinki.fi>

# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

'''
Handle URLs of the form "/coast/([0-9a-f]{40})/(.*)".
'''

import web
import simplejson
import os
from fusion.db.db import hex_to_bytes, bytes_to_hex
from fusion.http.util import withdb
from fusion.tracker.Tracker_collection import Tracker_collection

class Coast(object):

    @withdb
    def feedi(self, db, islands, feedtitle):
        import os.path
        import xml.etree.ElementTree as ET
        from fusion.http.server import MAIN

        root = ET.Element('feed')
        root.set('xmlns', 'http://www.w3.org/2005/Atom')
        id = ET.SubElement(root, "id")
        id.text = 'tag:hiit.fi,2007-06:atom_feed'
        title = ET.SubElement(root, 'title')
        title.text = feedtitle

        for collection in islands:
            tracker = Tracker_collection(collection)

            published = tracker.published(db)

            for info_hash in published:
                files = [file for file in db.keys(collection, 'island/'+info_hash) if os.path.split(file)[0] == 'file']

                for file in files:
                    filename = os.path.split(file)[1]
                    fileinfo = None

                    try:
                        fileinfo = simplejson.loads(db.get(collection, 'island/'+info_hash+'/info/'+filename+'/info'))

                    except:
                        pass

                    sub = ET.SubElement(root, 'entry')
                    title = ET.SubElement(sub, 'title')

                    title.text = filename

                    if filename[-8:] == '.torrent':
                        title.text = filename[:-8]


                    link = ET.SubElement(sub, 'link')
                    link.set('href', MAIN+'/collection/'+collection+'/island/'+info_hash+'/'+file)
                    published = ET.SubElement(sub, 'published')

                    try:
                        published.text = fileinfo['published']

                    except:
                        published.text = 'Unknown'

                    content = ET.SubElement(sub, 'content')

                    try:
                        content.text = fileinfo['description']

                    except:
                        content.text = ''

                    try:
                        publisher = fileinfo['publisher']['name']
                    except:
                        pass

                    if publisher:
                        author = ET.SubElement(sub, 'author')
                        name = ET.SubElement(author, 'name')
                        name.text = publisher
                        try:
                            profile = fileinfo['publisher']['profile']
                            profile_link = 'http://localhost:8080/profile/' + profile
                            
                            uri = ET.SubElement(author, 'uri')

                            uri.text = profile_link

                        except:
                            pass

        web.header('Content-Type', 'application/atom+xml')
        out =  '<?xml version="1.0" encoding="UTF-8"?>'
        out += ET.tostring(root)
        web.output(out)

    @withdb
    def GET(self, db, collection, request=''):

        input = web.input(output='', timeout='')

        timeout = None
        block = True
        
        if input.timeout:
            try:
                timeout = float(input.timeout)
                block = (timeout > 0)
            except ValueError:
                return web.badrequest()

        try:
            db.keys(collection,
                    autoimport = True,
                    block = block,
                    timeout = timeout)
        except NoSuchCollection:
            return web.notfound()
        
        for island in self.reachable_islands(db,collection):
            try:
                db.keys(island,
                        autoimport = True,
                        block = block,
                        timeout = 0)
            except NoSuchCollection:
                return web.notfound()

        if request == 'feed':
            self.feed(collection)

        if request == 'teachpilot':
            self.teachpilot(collection)
            
        if request == 'hash':
            from sha import sha
            from fusion.db.db import bytes_to_hex
            i = bytes_to_hex(sha(web.input(string='').string).digest())
            web.output(i)
        return


    def reachable_islands(self,db,coast):
        pilots = [simplejson.loads(p) for p in db.get_view(coast,'coast/pilots').values()]

        islands = []
        for pilot in pilots:
            islands += pilot

        return [i for i in islands if len(i)==40]


    @withdb
    def feed(self, db, coast):

        
        self.feedi(self.reachable_islands(db,coast), db.get(coast, 'info/title'))


    @withdb
    def teachpilot(self, db, collection):

        input = web.input(island='')

        fingerprint = bytes_to_hex(db.get_default_identity().get_fingerprint())

        pilot = db.get(collection, 'coast/pilots/0x' + fingerprint)
        if (pilot):
            islands = set(simplejson.loads(pilot))
        else:
            islands = set()

        islands.add(input.island)

        pilot = simplejson.dumps(list(islands))

        db.post(collection, 'coast/pilots', pilot)
